home *** CD-ROM | disk | FTP | other *** search
/ Delphi Magazine Collection 2001 / Delphi Magazine Collection 20001 (2001).iso / DISKS / ISSUE20 / CLINIC / Directio / TOTALIO / TOTALIO.C < prev   
Encoding:
C/C++ Source or Header  |  1996-04-03  |  3.9 KB  |  135 lines

  1. /*********************************************************************
  2.  
  3. Author:     Dale Roberts
  4. Date:       8/30/95
  5. Program:    TOTALIO.SYS
  6. Compile:    Use DDK BUILD facility
  7.  
  8. Purpose:    Give direct port I/O access to the whole system.
  9.  
  10.   This driver grants total system-wide I/O access to all applications.
  11. Very dangerous, but useful for short tests.  Note that no test
  12. application is required.  Just use control panel or
  13. "net start totalio" to start the device driver.  When the driver
  14. is stopped, total I/O is removed.  Because no Win32 app needs to
  15. communicate with the driver, we don't have to create a device object.
  16. So we have a very tiny driver here.
  17.  
  18. Since we can safely extend the TSS only to the end of the physical
  19. memory page in which it lies, the I/O access is granted only up to
  20. port 0xf00.  Accesses beyond this port address will still generate
  21. exceptions.
  22.  
  23. *********************************************************************/
  24. #include <ntddk.h>
  25.  
  26. /*
  27.  *  Make sure our structure is packed properly, on byte boundary, not
  28.  * on the default doubleword boundary.
  29. */
  30. #pragma pack(push,1)
  31.  
  32. /*
  33.  *  Structures for manipulating the GDT register and a GDT segment
  34.  * descriptor entry.  Documented in Intel processor handbooks.
  35.  */
  36. typedef struct {
  37.     unsigned limit : 16;
  38.     unsigned baselo : 16;
  39.     unsigned basemid : 8;
  40.     unsigned type : 4;
  41.     unsigned system : 1;
  42.     unsigned dpl : 2;
  43.     unsigned present : 1;
  44.     unsigned limithi : 4;
  45.     unsigned available : 1;
  46.     unsigned zero : 1;
  47.     unsigned size : 1;
  48.     unsigned granularity : 1;
  49.     unsigned basehi : 8;
  50. } GDTENT;
  51.  
  52. typedef struct {
  53.     unsigned short    limit;
  54.     GDTENT    *base;
  55. } GDTREG;
  56.  
  57. #pragma pack(pop)
  58.  
  59. /*
  60.  *  This is the lowest level for setting the TSS segment descriptor
  61.  * limit field.  We get the selector ID from the STR instruction,
  62.  * index into the GDT, and poke in the new limit.  In order for the
  63.  * new limit to take effect, we must then read the task segment
  64.  * selector back into the task register (TR).
  65.  */
  66. void SetTSSLimit(int size)
  67. {
  68.     GDTREG gdtreg;
  69.     GDTENT *g;
  70.     short TaskSeg;
  71.  
  72.     _asm cli;                            // don't get interrupted!
  73.     _asm sgdt gdtreg;                    // get GDT address
  74.     _asm str TaskSeg;                    // get TSS selector index
  75.     g = gdtreg.base + (TaskSeg >> 3);    // get ptr to TSS descriptor
  76.     g->limit = size;                    // modify TSS segment limit
  77. //
  78. //  MUST set selector type field to 9, to indicate the task is
  79. // NOT BUSY.  Otherwise the LTR instruction causes a fault.
  80. //
  81.     g->type = 9;                        // mark TSS as "not busy"
  82. //
  83. //  We must do a load of the Task register, else the processor
  84. // never sees the new TSS selector limit.
  85. //
  86.     _asm ltr TaskSeg;                    // reload task register (TR)
  87.     _asm sti;                            // let interrupts continue
  88. }
  89.     
  90. /*
  91.  *  This routine gives total I/O access across the whole system.
  92.  * It does this by modifying the limit of the TSS segment by direct
  93.  * modification of the TSS descriptor entry in the GDT.
  94.  * This descriptor is set up just once at sysetem init time.  Once we
  95.  * modify it, it stays untouched across all processes.
  96.  */
  97. void GiveTotalIO(void)
  98. {
  99.     SetTSSLimit(0x20ab + 0xf00);
  100. }
  101.  
  102. /*
  103.  *  This returns the TSS segment to its normal size of 0x20ab, which
  104.  * is two less than the default I/O map base address of 0x20ad.
  105.  */
  106. void RemoveTotalIO(void)
  107. {
  108.     SetTSSLimit(0x20ab);
  109. }
  110.  
  111. /****************************************************************************
  112.   Release all memory 'n' stuff.
  113. ****************************************************************************/
  114. VOID
  115. TotalIOdrvUnload(
  116.     IN  PDRIVER_OBJECT  DriverObject
  117.     )
  118. {
  119.     RemoveTotalIO();
  120. }
  121.  
  122. /****************************************************************************
  123.   Entry routine.  Set everything up.
  124. ****************************************************************************/
  125. NTSTATUS DriverEntry(
  126.     IN PDRIVER_OBJECT DriverObject,
  127.     IN PUNICODE_STRING RegistryPath
  128.     )
  129. {
  130.     DriverObject->DriverUnload = TotalIOdrvUnload;
  131.     GiveTotalIO();
  132.     return STATUS_SUCCESS;
  133. }
  134.  
  135.